#include "request.h"
#include "common/str.h"
#include "common/log.h"


namespace evm { namespace http {

Request& Request::operator=(Request&& r) {
    method = r.method;
    url = std::move(r.url);
    path = std::move(r.path);
    query_paras = std::move(r.query_paras);
    headers = std::move(r.headers);
    body = std::move(r.body);
    json = r.json;
    return *this;
}

void Request::clear() {
    method = GET;
    url.clear();
    path.clear();
    query_paras.clear();
    headers.clear();
    body.clear();
    json.clear();
    path_paras.clear();
    has_file = false;
    file_name.clear();
    content_length = 0;
    file_handler = nullptr;
}

string Request::get_query(const string &field) const {
    auto it = query_paras.find(field);
    if (it != query_paras.cend())
        return it->second;
    else
        return "";
}

bool Request::has_query(const string &field) const {
    return query_paras.find(field) != query_paras.cend();
}

bool Request::has_query(const string &field, const string &value) const {
    auto range = query_paras.equal_range(field);
    for (auto it = range.first; it != range.second; ++it) {
        if (it->second == value)
            return true;
    }

    return false;
}

const string& Request::get_header(const string& field) const {
    return http::get_header(headers, field);
}

bool Request::has_header(const string& field) const {
    return headers.count(field) > 0;
}

bool Request::has_header(const string& field, const string& value) const {
    return str::iequals(http::get_header(headers, field), value);
}

auto Request::operator[](const char* key) -> decltype(json[""]) {
    return json[key];
}

auto Request::operator[](const string& key) -> decltype(json[""]) {
    return json[key.data()];
}

string Request::str() const {
    static map<HTTPMethod, string> to_str = {
            {GET, "GET"},
            {HEAD, "HEAD"},
            {POST, "POST"},
            {PUT, "PUT"},
            {DELETE, "DELETE"},
            {CONNECT, "CONNECT"},
            {OPTIONS, "OPTIONS"},
            {TRACE, "TRACE"}
    };
    string s;
    s += "\n" + to_str[method] + " " + url + "\n"
         + "path: " + path + "\n";
    s += "query_paras:\n";
    for (const auto& i: query_paras)
        s += "\t" + i.first + ": " + i.second + "\n";
    s += "headers:\n";
    for (const auto& i: headers)
        s += "\t" + i.first + ": " + i.second + "\n";
    if (!json.empty())
        s += "json:\n" + json.dump(2);
    else
        s += "body:\n" + body;
    return s;
}

}}
